/*
 * Copyright (C) 2005 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.frame;

import java.util.ArrayList;

import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.WorkbenchFrameListener;
import nu.zoom.swing.desktop.WorkbenchMenuBar;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ops4j.gaderian.Messages;

/**
 * Keeps track of the existing workbench frames.
 */
class WorkbenchFrames implements WorkbenchFrameListener {

    private final Log log = LogFactory.getLog(getClass());
    private final ArrayList<WorkbenchFrame> frames = new ArrayList<WorkbenchFrame>();
    private boolean closing = false;
    private final WorkbenchFramesMenu menuHandler;

    public WorkbenchFrames(Messages messages, WorkbenchMenuBar menuBar) {
        menuHandler = new WorkbenchFramesMenu(messages, menuBar);
    }

    /**
     * Must be called on the eventqueue
     *
     * @param frame
     *            The frame that is added to the desktop.
     */
    synchronized void addFrame(final WorkbenchFrame frame) {
        log.trace("Adding frame");
        frames.add(frame);
        frame.addFrameListener(this);
        menuHandler.addFrame(frame);
    }

    synchronized String getUniqueTitle(String title) {
        log.trace("Finding unique frame title for title:" + title);
        // Construct a title. If several frames have the same title
        // add a serial number (starting at 2) to the title until we have a
        // unique title.
        boolean titleIsUnique;
        int titleIndex = 1;
        String compoundTitle = title;
        do {
            titleIsUnique = true;
            for (int f = 0; ((titleIsUnique) && (f < frames.size())); f++) {
                log.trace("Checking if title " + compoundTitle + " is unique");
                String currentTitle = frames.get(f).getTitle();
                if (titleIndex < 2) {
                    if (currentTitle.equals(compoundTitle)) {
                        titleIsUnique = false;
                        titleIndex++;
                    }
                } else {
                    compoundTitle = title + " : " + titleIndex;
                    if (currentTitle.equals(compoundTitle)) {
                        titleIsUnique = false;
                        titleIndex++;
                    }
                }
            }
        } while (!titleIsUnique);
        log.trace("Frame title was " + title + " adjusted to " + compoundTitle);
        return compoundTitle;
    }

    /**
     * Informs the menus that a frame has changed title.
     *
     * @param oldTitle
     * @param newTitle
     */
    synchronized void titleChanged(final WorkbenchFrame frame) {
        log.trace("Title changed event");
        menuHandler.removeFrame(frame);
        menuHandler.addFrame(frame);
    }

    /**
     * Must be called on the eventqueue. Drops all frame references.
     *
     */
    synchronized void closeAll() {
        log.trace("Closing all frames");
        closing = true;
        for (int i = 0; i < frames.size(); i++) {
            frames.get(i).dispose();
        }
        frames.clear();
        menuHandler.clear();
    }

    @Override
    public synchronized void frameClosed(WorkbenchFrame frame) {
        if (closing) {
            // If we are closing all frames we do not want to modify the frame
            // collection. This is a callback from the closeAll procedure when
            // disposing all frames.
            log.trace("Frame closed event due to this class disposing of it");
            return;
        } else {
            log.trace("Frame closed event, not originating from this class");
            frames.remove(frame);
            menuHandler.removeFrame(frame);
        }
    }

    @Override
    public void frameWillDispose(WorkbenchFrame frame) {
    }

    @Override
    public void frameDetached(WorkbenchFrame frame) {
    }

    @Override
    public void frameAttached(WorkbenchFrame frame) {
    }
}
